using System;
using System.IO;
using System.Text;
using UnityEngine;

namespace Framework
{
    public class ByteArray
    {
        public int ReadAvailable { get { return _buffer.Length - _position; } }
        public int Position { get { return _position; } }
        public ByteBuffer Buffer { get { return _buffer; } }
        private ByteBuffer _buffer;
        private int _position;
        public ByteArray(byte[] buffer) : this(new ByteBuffer(buffer))
        {

        }
        public ByteArray(int size) : this(new ByteBuffer(size))
        {

        }
        public ByteArray(ByteBuffer buffer, int offset = 0)
        {
            _buffer = buffer;
            _position = offset;
        }
        public void Dispose()
        {
            _buffer.Dispose();
            _buffer = null;
        }
        public void Clear()
        {
            _position = 0;
        }
        public void CopyTo(Array dst, int count = 0, int dstOffset = 0)
        {
            if (count < 1)
            {
                count = _position;
            }
            _buffer.CopyTo(dst, count, dstOffset, 0);
        }
        public void SetPosition(int value)
        {
            _position = value;
        }
        //读取
        public byte ReadByte()
        {
            return _buffer.Read((_position += 1) - 1);
        }
        public sbyte ReadSbyte()
        {
            return _buffer.ReadSbyte((_position += 1) - 1);
        }
        public bool ReadBool()
        {
            return ReadByte() == 1;
        }

        public short ReadShort()
        {
            return _buffer.ReadShort((_position += 2) - 2);
        }

        public ushort ReadUshort()
        {
            return _buffer.ReadUshort((_position += 2) - 2);
        }

        public int ReadInt()
        {
            return _buffer.ReadInt((_position += 4) - 4);
        }

        public uint ReadUint()
        {
            return _buffer.ReadUint((_position += 4) - 4);
        }
        public float ReadFloat()
        {
            return _buffer.ReadFloat((_position += 4) - 4);
        }
        public long ReadLong()
        {
            return _buffer.ReadLong((_position += 8) - 8);
        }

        public ulong ReadUlong()
        {
            return _buffer.ReadUlong((_position += 8) - 8);
        }
        public double ReadDouble()
        {
            return _buffer.ReadDouble((_position += 8) - 8);
        }

        public string ReadString()
        {
            ushort count = ReadUshort();
            var str = _buffer.ReadStringUTF8((_position += count) - count, count);
            return str;
        }
        public string ReadShortString()
        {
            sbyte count = ReadSbyte();
            var str = _buffer.ReadStringUTF8((_position += count) - count, count);
            return str;
        }
        //写入
        public void WriteByte(byte value)
        {
            Write(value);
        }
        public void WriteSbyte(sbyte value)
        {
            Write(value);
        }
        public void WriteBool(bool value)
        {
            Write(value);
        }

        public void WriteShort(short value)
        {
            Write(value);
        }

        public void WriteUShort(ushort value)
        {
            Write(value);
        }

        public void WriteInt(int value)
        {
            Write(value);
        }

        public void WriteUint(uint value)
        {
            Write(value);
        }
        public void WriteFloat(float value)
        {
            Write(value);
        }
        public void WriteLong(long value)
        {
            Write(value);
        }

        public void WriteUlong(ulong value)
        {
            Write(value);
        }
        public void WriteDouble(double value)
        {
            Write(value);
        }

        public void WriteString(string value)
        {
            Write(value);
        }
        public void WriteShortString(string value)
        {
            sbyte count = (sbyte)Encoding.UTF8.GetByteCount(value);
            Write(count);
            PrepareSize(count);
            _position += _buffer.Write(_position, value);
        }
        public void PrepareSize(int value)
        {
            _buffer.SetSize(_position + value);
        }
        public void Write(bool value)
        {
            PrepareSize(1);
            _position += _buffer.Write(_position, value ? (byte)1 : (byte)0);
        }
        public void Write(sbyte value)
        {
            PrepareSize(1);
            _position += _buffer.Write(_position, value);
        }
        public void Write(byte value)
        {
            PrepareSize(1);
            _position += _buffer.Write(_position, value);
        }
        public void Write(string value)
        {
            ushort count = (ushort)Encoding.UTF8.GetByteCount(value);
            WriteUShort(count);
            PrepareSize(count);
            _position += _buffer.Write(_position, value);
        }
        public void Write(short value)
        {
            PrepareSize(2);
            _position += _buffer.Write(_position, value);
        }
        public void Write(ushort value)
        {
            PrepareSize(2);
            _position += _buffer.Write(_position, value);
        }
        public void Write(int value)
        {
            PrepareSize(4);
            _position += _buffer.Write(_position, value);
        }
        public void Write(uint value)
        {
            PrepareSize(4);
            _position += _buffer.Write(_position, value);
        }
        public void Write(long value)
        {
            PrepareSize(8);
            _position += _buffer.Write(_position, value);
        }
        public void Write(ulong value)
        {
            PrepareSize(8);
            _position += _buffer.Write(_position, value);
        }
        public void Write(float value)
        {
            PrepareSize(4);
            _position += _buffer.Write(_position, value);
        }
        public void Write(double value)
        {
            PrepareSize(8);
            _position += _buffer.Write(_position, value);
        }
        public void Write<T>(T[] src, int srcOffset = 0, int count = 0) where T : struct
        {
            if (src == null)
            {
                throw new ArgumentException("src null"); ;
            }
            if (src.Length == 0)
            {
                throw new ArgumentException("src.Length error");
            }
            if (srcOffset < 0)
            {
                throw new ArgumentException("srcOffset less than zero");
            }
            int elememtCount = src.Length - srcOffset;
            if (count < 1)
            {
                count = elememtCount;
            }
            else
            {
                if (count > elememtCount)
                {
                    throw new ArgumentException("Count bigger than Length-srcOffset");
                }
            }
            if (!ByteBuffer.IsSupportedType<T>())
            {
                string str = "Cannot add an array of type ";
                Type typeFromHandle = typeof(T);
                throw new ArgumentException(str + (typeFromHandle?.ToString()) + " into this buffer");
            }
            int num = ByteBuffer.SizeOf<T>() * count;
            PrepareSize(num);
            _position += _buffer.Write(_position, src, srcOffset, count);
        }
    }
}